package com.example.demo.service.impl;

import com.example.demo.exception.BusinessException;
import com.example.demo.mapper.ResearchPaperMapper;
import com.example.demo.model.dto.PaperSubmissionDTO;
import com.example.demo.model.dto.PaperSubmissionDTO.AuthorInfo;
import com.example.demo.model.entity.achievement.ResearchPaper;
import com.example.demo.model.entity.audit.AuditRecord;
import com.example.demo.model.enums.PaperStatusEnum;
import com.example.demo.security.CustomUserDetails;
import com.example.demo.service.PaperService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import com.example.demo.mapper.AuditRecordMapper;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@Validated
@RequiredArgsConstructor
public class PaperServiceImpl implements PaperService {

    private final ResearchPaperMapper paperMapper;
    private final ObjectMapper objectMapper;
    private final AuditRecordMapper auditRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResearchPaper submitPaper(PaperSubmissionDTO submissionDTO) {
        try {
            log.debug("论文提交数据: {}", maskSensitiveData(submissionDTO));
            ResearchPaper paper = convertAndValidate(submissionDTO);
            paper.setStatusEnum(PaperStatusEnum.SUBMITTED);
            setSystemFields(paper);
            saveWithRetry(paper, 3, 1000);
            return paper;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("论文提交系统异常", e);
            throw new BusinessException("系统处理失败，请稍后重试");
        }
    }

    @Override
    public ResearchPaper updateStudentPaper(Long paperId, PaperSubmissionDTO updateDTO) {
        Optional<ResearchPaper> optionalPaper = paperMapper.findById(paperId);
        if (!optionalPaper.isPresent()) {
            throw new BusinessException("论文不存在");
        }
        ResearchPaper paper = optionalPaper.get();
        if (!paper.getStatusEnum().canBeModified()) {
            throw new BusinessException("当前状态不允许修改");
        }
        try {
            ResearchPaper updatedPaper = convertAndValidate(updateDTO);
            paper.setPaperTitle(updatedPaper.getPaperTitle());
            paper.setJournal(updatedPaper.getJournal());
            paper.setIssue(updatedPaper.getIssue());
            paper.setVolume(updatedPaper.getVolume());
            paper.setPageRange(updatedPaper.getPageRange());
            paper.setIndexLevel(updatedPaper.getIndexLevel());
            paper.setAuthors(updatedPaper.getAuthors());
            paper.setFirstAuthor(updatedPaper.getFirstAuthor());
            paper.setCorrespondingAuthor(updatedPaper.getCorrespondingAuthor());
            paper.setPublishDate(updatedPaper.getPublishDate());
            paper.setImpactFactor(updatedPaper.getImpactFactor());
            paper.setPaperLink(updatedPaper.getPaperLink());
            paper.setUpdateTime(LocalDateTime.now());
            int result = paperMapper.update(paper);
            if (result == 0) {
                throw new BusinessException("论文更新失败");
            }
            return paper;
        } catch (JsonProcessingException e) {
            throw new BusinessException("数据处理错误", e);
        }
    }

    @Override
    public void deleteStudentPaper(Long paperId) {
        Optional<ResearchPaper> optionalPaper = paperMapper.findById(paperId);
        if (!optionalPaper.isPresent()) {
            throw new BusinessException("论文不存在");
        }
        ResearchPaper paper = optionalPaper.get();
        if (!paper.getStatusEnum().canBeDeleted()) {
            throw new BusinessException("当前状态不允许删除");
        }
        int result = paperMapper.delete(paperId);
        if (result == 0) {
            throw new BusinessException("论文删除失败，可能论文不存在");
        }
    }

    @Override
    public List<ResearchPaper> getStudentPapers() {
        Long currentUserId = getCurrentUserId();
        return paperMapper.findBySubmitUserId(currentUserId);
    }

    @Override
    public ResearchPaper getStudentPaperById(Long paperId) {
        Optional<ResearchPaper> optionalPaper = paperMapper.findById(paperId);
        return optionalPaper.orElseThrow(() -> new BusinessException("论文不存在"));
    }

    @Override
    public List<ResearchPaper> getPendingReviewPapers() {
        return paperMapper.findByStatus(PaperStatusEnum.SUBMITTED);
    }



    // 在 PaperServiceImpl 类中
    private ResearchPaper convertAndValidate(PaperSubmissionDTO dto) throws JsonProcessingException {
        ResearchPaper paper = new ResearchPaper();
        paper.setPaperTitle(dto.getPaperTitle());
        paper.setJournal(dto.getJournal());
        paper.setIssue(dto.getIssue());
        paper.setVolume(dto.getVolume());
        paper.setPageRange(dto.getPageRange());
        paper.setIndexLevel(dto.getIndexLevel());

        validateAuthors(dto.getAuthors());
        paper.setAuthors(objectMapper.writeValueAsString(dto.getAuthors()));

        paper.setFirstAuthor(dto.getFirstAuthor());
        paper.setCorrespondingAuthor(dto.getCorrespondingAuthor());
        paper.setPublishDate(dto.getPublishDate());

        // 修正 impactFactor 处理 - 直接使用 Double 类型
        paper.setImpactFactor(dto.getImpactFactor());

        paper.setPaperLink(dto.getPaperLink());

        return paper;
    }

    private void validateAuthors(List<AuthorInfo> authors) {
        if (authors == null || authors.isEmpty()) {
            throw new BusinessException("作者列表不能为空");
        }
        if (authors.stream().map(AuthorInfo::getOrder).distinct().count() != authors.size()) {
            throw new BusinessException("作者排序序号不能重复");
        }
    }

    private void setSystemFields(ResearchPaper paper) {
        paper.setSubmitUserId(getCurrentUserId());
        LocalDateTime now = LocalDateTime.now();
        paper.setCreateTime(now);
        paper.setUpdateTime(now);
    }

    private void saveWithRetry(ResearchPaper paper, int maxRetries, long delayMs) {
        int attempt = 0;
        while (attempt <= maxRetries) {
            try {
                paperMapper.insert(paper);
                log.info("论文保存成功，ID: {}", paper.getId());
                return;
            } catch (DuplicateKeyException e) {
                throw new BusinessException("相同标题的论文已存在");
            } catch (DataAccessException e) {
                attempt++;
                if (attempt > maxRetries) {
                    log.error("数据库操作重试失败", e);
                    throw new BusinessException("系统繁忙，请稍后重试");
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(delayMs * attempt);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new BusinessException("系统操作中断");
                }
            }
        }
    }

    private String maskSensitiveData(PaperSubmissionDTO dto) {
        return dto.toString()
                .replaceAll("(\"paperLink\":\")(.*?)(\")", "$1***$3")
                .replaceAll("(\"affiliation\":\")(.*?)(\")", "$1***$3");
    }

    // 在PaperServiceImpl中添加
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
            // 假设你的UserDetails实现类中有getUserId()方法
            return ((CustomUserDetails) authentication.getPrincipal()).getUserId();
        }
        throw new BusinessException("无法获取当前用户信息");
    }

    @Override
    public List<AuditRecord> getPaperAuditRecords(Long paperId) {
        Optional<ResearchPaper> optionalPaper = paperMapper.findById(paperId);
        if (!optionalPaper.isPresent()) {
            throw new BusinessException("论文不存在");
        }
        return auditRecordMapper.findByAchievementId(paperId);
    }
}